#ifndef __GWCONVERTSHELL_HPP__
#define __GWCONVERTSHELL_HPP__

#include <string>

/**
*@file       gwconvertshell.hpp
*@brief      makes some user data types have a ability to convert to some other general types
*
*@author     graywind
*@version    1.0.0.0
*@data       2011/12/27
*/

///util stuff
namespace gwBedrockUtil
{
        ///makes some user data types have a ability to convert to some other general types
        template<class oriType, template<class,class> class gwCastFunc>
        class gwConvertShell;
}

///util stuff
namespace gwBedrockUtil
{
        ///makes some user data types have a ability to convert to some other general types
        template<class oriType, template<class,class> class gwCastFunc>
        class gwConvertShell
        {
        public:
                ///@brief       original data type
                typedef oriType       OriginalType;
        private:
                ///@brief       data value hold by this class
                oriType               m_value;

        public:
                ///@brief       constructor
                gwConvertShell();
                ///@brief       constructor
                ///param[in]    rhs        copy from original data type object
                gwConvertShell(const OriginalType& rhs);
                ///@brief       copy constructor
                ///param[in]    gwconvertshell      create instance from another
                gwConvertShell(const gwConvertShell<oriType, gwCastFunc>& rhs);
                ///@brief       destructor
                ~gwConvertShell();

        public:
                ///@brief       override operator+
                ///param[in]    rhs      original data type object
                ///retval       gwConvertShell      make a new gwConvertShell object hold the new value
                gwConvertShell<oriType,gwCastFunc>    operator+(const OriginalType& rhs) const;
                ///@brief       override operator-
                ///param[in]    rhs      original data type object
                ///retval       gwConvertShell      make a new gwConvertShell object hold the new value
                gwConvertShell<oriType,gwCastFunc>    operator-(const OriginalType& rhs) const;
                ///@brief       override operator*
                ///param[in]    rhs      original data type object
                ///retval       gwConvertShell      make a new gwConvertShell object hold the new value
                gwConvertShell<oriType,gwCastFunc>    operator*(const OriginalType& rhs) const;
                ///@brief       override operator/
                ///param[in]    rhs      original data type object
                ///retval       gwConvertShell      make a new gwConvertShell object hold the new value
                gwConvertShell<oriType,gwCastFunc>    operator/(const OriginalType& rhs) const;
                ///@brief       override operator+
                ///param[in]    rhs      another gwConvertShell instance(must be the same type)
                ///retval       gwConvertShell      make a new gwConvertShell object hold the new value
                gwConvertShell<oriType,gwCastFunc>    operator+(const gwConvertShell<oriType,gwCastFunc>& rhs) const;
                ///@brief       override operator-
                ///param[in]    rhs      another gwConvertShell instance(must be the same type)
                ///retval       gwConvertShell      make a new gwConvertShell object hold the new value
                gwConvertShell<oriType,gwCastFunc>    operator-(const gwConvertShell<oriType,gwCastFunc>& rhs) const;
                ///@brief       override operator*
                ///param[in]    rhs      another gwConvertShell instance(must be the same type)
                ///retval       gwConvertShell      make a new gwConvertShell object hold the new value
                gwConvertShell<oriType,gwCastFunc>    operator*(const gwConvertShell<oriType,gwCastFunc>& rhs) const;
                ///@brief       override operator/
                ///param[in]    rhs      another gwConvertShell instance(must be the same type)
                ///retval       gwConvertShell      make a new gwConvertShell object hold the new value
                gwConvertShell<oriType,gwCastFunc>    operator/(const gwConvertShell<oriType,gwCastFunc>& rhs) const;

                ///@brief       override operator+=
                ///param[in]    rhs      original data type object
                ///retval       void
                void                               operator+=(const OriginalType& rhs);
                ///@brief       override operator-=
                ///param[in]    rhs      original data type object
                ///retval       void
                void                               operator-=(const OriginalType& rhs);
                ///@brief       override operator*=
                ///param[in]    rhs      original data type object
                ///retval       void
                void                               operator*=(const OriginalType& rhs);
                ///@brief       override operator/=
                ///param[in]    rhs      original data type object
                ///retval       void
                void                               operator/=(const OriginalType& rhs);
                ///@brief       override operator+=
                ///param[in]    rhs      another gwConvertShell instance(must be the same type)
                ///retval       void
                void                               operator+=(const gwConvertShell<oriType,gwCastFunc>& rhs);
                ///@brief       override operator-=
                ///param[in]    rhs      another gwConvertShell instance(must be the same type)
                ///retval       void
                void                               operator-=(const gwConvertShell<oriType,gwCastFunc>& rhs);
                ///@brief       override operator*=
                ///param[in]    rhs      another gwConvertShell instance(must be the same type)
                ///retval       void
                void                               operator*=(const gwConvertShell<oriType,gwCastFunc>& rhs);
                ///@brief       override operator/=
                ///param[in]    rhs      another gwConvertShell instance(must be the same type)
                ///retval       void
                void                               operator/=(const gwConvertShell<oriType,gwCastFunc>& rhs);


                ///@brief       override operator=
                ///param[in]    rhs      original data type object
                ///retval       gwConvertShell      return reference of this object
                gwConvertShell<oriType, gwCastFunc>&   operator=(const OriginalType& rhs);
                ///@brief       override operator=
                ///param[in]    rhs      another gwConvertShell instance(must be the same type)
                ///retval       gwConvertShell      return reference of this object
                gwConvertShell<oriType, gwCastFunc>&   operator=(const gwConvertShell<oriType, gwCastFunc>& rhs);

                ///@brief       override operator<
                ///param[in]    rhs      original data type object
                ///retval       bool
                bool                               operator<(const OriginalType& rhs) const;
                ///@brief       override operator>
                ///param[in]    rhs      original data type object
                ///retval       bool
                bool                               operator>(const OriginalType& rhs) const;
                ///@brief       override operator<=
                ///param[in]    rhs      original data type object
                ///retval       bool
                bool                               operator<=(const OriginalType& rhs) const;
                ///@brief       override operator>=
                ///param[in]    rhs      original data type object
                ///retval       bool
                bool                               operator>=(const OriginalType& rhs) const;
                ///@brief       override operator==
                ///param[in]    rhs      original data type object
                ///retval       bool
                bool                               operator==(const OriginalType& rhs) const;
                ///@brief       override operator!=
                ///param[in]    rhs      original data type object
                ///retval       bool
                bool                               operator!=(const OriginalType& rhs) const;
                ///@brief       override operator<
                ///param[in]    rhs      another gwConvertShell instance(must be the same type)
                ///retval       bool
                bool                               operator<(const gwConvertShell<oriType,gwCastFunc>& rhs) const;
                ///@brief       override operator>
                ///param[in]    rhs      another gwConvertShell instance(must be the same type)
                ///retval       bool
                bool                               operator>(const gwConvertShell<oriType,gwCastFunc>& rhs) const;
                ///@brief       override operator<=
                ///param[in]    rhs      another gwConvertShell instance(must be the same type)
                ///retval       bool
                bool                               operator<=(const gwConvertShell<oriType,gwCastFunc>& rhs) const;
                ///@brief       override operator>=
                ///param[in]    rhs      another gwConvertShell instance(must be the same type)
                ///retval       bool
                bool                               operator>=(const gwConvertShell<oriType,gwCastFunc>& rhs) const;
                ///@brief       override operator==
                ///param[in]    rhs      another gwConvertShell instance(must be the same type)
                ///retval       bool
                bool                               operator==(const gwConvertShell<oriType,gwCastFunc>& rhs) const;
                ///@brief       override operator!=
                ///param[in]    rhs      another gwConvertShell instance(must be the same type)
                ///retval       bool
                bool                               operator!=(const gwConvertShell<oriType,gwCastFunc>& rhs) const;

        public:
                ///@brief       convert to bool
                bool                               AsBoolen()      const;
                ///@brief       convert to char
                char                               AsChar()        const;
                ///@brief       convert to short
                short                              AsShort()       const;
                ///@brief       convert to int
                int                                AsInt()         const;
                ///@brief       convert to long
                long                               AsLong()        const;
                ///@brief       convert to float
                float                              AsFloat()       const;
                ///@brief       convert to double
                double                             AsDouble()      const;
                ///@brief       convert to std::string
                std::string                        AsString()      const;
        };

        /***************************************************************************************************************************/
        template<class oriType, template<class,class> class gwCastFunc>
        gwConvertShell<oriType,gwCastFunc>::gwConvertShell()
        {

        }

        /***************************************************************************************************************************/
        template<class oriType, template<class,class> class gwCastFunc>
        gwConvertShell<oriType,gwCastFunc>::gwConvertShell(const typename gwConvertShell<oriType,gwCastFunc>::OriginalType& rhs):
        m_value(rhs)
        {

        }

        /***************************************************************************************************************************/
        template<class oriType, template<class,class> class gwCastFunc>
        gwConvertShell<oriType,gwCastFunc>::gwConvertShell(const gwConvertShell<oriType,gwCastFunc>& rhs):
        m_value(rhs.m_value)
        {

        }

        /***************************************************************************************************************************/
        template<class oriType, template<class,class> class gwCastFunc>
        gwConvertShell<oriType,gwCastFunc>::~gwConvertShell()
        {

        }

        /***************************************************************************************************************************/
        template<class oriType, template<class,class> class gwCastFunc>
        gwConvertShell<oriType,gwCastFunc>
        gwConvertShell<oriType,gwCastFunc>::operator+(const gwConvertShell<oriType,gwCastFunc>& rhs) const
        {
                return gwConvertShell<oriType,gwCastFunc>(m_value + rhs.m_value);
        }

        /***************************************************************************************************************************/
        template<class oriType, template<class,class> class gwCastFunc>
        gwConvertShell<oriType,gwCastFunc>
        gwConvertShell<oriType,gwCastFunc>::operator-(const gwConvertShell<oriType,gwCastFunc>& rhs) const
        {
                return gwConvertShell<oriType,gwCastFunc>(m_value - rhs.m_value);
        }

        /***************************************************************************************************************************/
        template<class oriType, template<class,class> class gwCastFunc>
        gwConvertShell<oriType,gwCastFunc>
        gwConvertShell<oriType,gwCastFunc>::operator*(const gwConvertShell<oriType,gwCastFunc>& rhs) const
        {
                return gwConvertShell<oriType,gwCastFunc>(m_value * rhs.m_value);
        }

        /***************************************************************************************************************************/
        template<class oriType, template<class,class> class gwCastFunc>
        gwConvertShell<oriType,gwCastFunc>
        gwConvertShell<oriType,gwCastFunc>::operator/(const gwConvertShell<oriType,gwCastFunc>& rhs) const
        {
                return gwConvertShell<oriType,gwCastFunc>(m_value / rhs.m_value);
        }

        /***************************************************************************************************************************/
        template<class oriType, template<class,class> class gwCastFunc>
        gwConvertShell<oriType,gwCastFunc>
        gwConvertShell<oriType,gwCastFunc>::operator+(const typename gwConvertShell<oriType,gwCastFunc>::OriginalType& rhs) const
        {
                return gwConvertShell<oriType,gwCastFunc>(m_value + rhs);
        }

        /***************************************************************************************************************************/
        template<class oriType, template<class,class> class gwCastFunc>
        gwConvertShell<oriType,gwCastFunc>
        gwConvertShell<oriType,gwCastFunc>::operator-(const typename gwConvertShell<oriType,gwCastFunc>::OriginalType& rhs) const
        {
                return gwConvertShell<oriType,gwCastFunc>(m_value - rhs);
        }

        /***************************************************************************************************************************/
        template<class oriType, template<class,class> class gwCastFunc>
        gwConvertShell<oriType,gwCastFunc>
        gwConvertShell<oriType,gwCastFunc>::operator*(const typename gwConvertShell<oriType,gwCastFunc>::OriginalType& rhs) const
        {
                return gwConvertShell<oriType,gwCastFunc>(m_value * rhs);
        }

        /***************************************************************************************************************************/
        template<class oriType, template<class,class> class gwCastFunc>
        gwConvertShell<oriType,gwCastFunc>
        gwConvertShell<oriType,gwCastFunc>::operator/(const typename gwConvertShell<oriType,gwCastFunc>::OriginalType& rhs) const
        {
                return gwConvertShell<oriType,gwCastFunc>(m_value / rhs);
        }

        /***************************************************************************************************************************/
        template<class oriType, template<class,class> class gwCastFunc>
        void
        gwConvertShell<oriType,gwCastFunc>::operator+=(const gwConvertShell<oriType,gwCastFunc>& rhs)
        {
                m_value += rhs.m_value;
        }

        /***************************************************************************************************************************/
        template<class oriType, template<class,class> class gwCastFunc>
        void
        gwConvertShell<oriType,gwCastFunc>::operator-=(const gwConvertShell<oriType,gwCastFunc>& rhs)
        {
                m_value -= rhs.m_value;
        }

        /***************************************************************************************************************************/
        template<class oriType, template<class,class> class gwCastFunc>
        void
        gwConvertShell<oriType,gwCastFunc>::operator*=(const gwConvertShell<oriType,gwCastFunc>& rhs)
        {
                m_value *= rhs.m_value;
        }

        /***************************************************************************************************************************/
        template<class oriType, template<class,class> class gwCastFunc>
        void
        gwConvertShell<oriType,gwCastFunc>::operator/=(const gwConvertShell<oriType,gwCastFunc>& rhs)
        {
                m_value /= rhs.m_value;
        }

        /***************************************************************************************************************************/
        template<class oriType, template<class,class> class gwCastFunc>
        void
        gwConvertShell<oriType,gwCastFunc>::operator+=(const typename gwConvertShell<oriType,gwCastFunc>::OriginalType& rhs)
        {
                m_value += rhs;
        }

        /***************************************************************************************************************************/
        template<class oriType, template<class,class> class gwCastFunc>
        void
        gwConvertShell<oriType,gwCastFunc>::operator-=(const typename gwConvertShell<oriType,gwCastFunc>::OriginalType& rhs)
        {
                m_value -= rhs;
        }

        /***************************************************************************************************************************/
        template<class oriType, template<class,class> class gwCastFunc>
        void
        gwConvertShell<oriType,gwCastFunc>::operator*=(const typename gwConvertShell<oriType,gwCastFunc>::OriginalType& rhs)
        {
                m_value *= rhs;
        }

        /***************************************************************************************************************************/
        template<class oriType, template<class,class> class gwCastFunc>
        void
        gwConvertShell<oriType,gwCastFunc>::operator/=(const typename gwConvertShell<oriType,gwCastFunc>::OriginalType& rhs)
        {
                m_value /= rhs;
        }

        /***************************************************************************************************************************/
        template<class oriType, template<class,class> class gwCastFunc>
        gwConvertShell<oriType,gwCastFunc>&
        gwConvertShell<oriType,gwCastFunc>::operator =(const gwConvertShell<oriType,gwCastFunc> &rhs)
        {
                m_value = rhs.m_value;
                return *this;
        }

        /***************************************************************************************************************************/
        template<class oriType, template<class,class> class gwCastFunc>
        gwConvertShell<oriType,gwCastFunc>&
        gwConvertShell<oriType,gwCastFunc>::operator =(const typename gwConvertShell<oriType,gwCastFunc>::OriginalType &rhs)
        {
                m_value = rhs;
                return *this;
        }

        /***************************************************************************************************************************/
        template<class oriType, template<class,class> class gwCastFunc>
        bool
        gwConvertShell<oriType,gwCastFunc>::operator ==(const gwConvertShell<oriType,gwCastFunc>& rhs) const
        {
                return m_value == rhs.m_value;
        }

        /***************************************************************************************************************************/
        template<class oriType, template<class,class> class gwCastFunc>
        bool
        gwConvertShell<oriType,gwCastFunc>::operator ==(const typename gwConvertShell<oriType,gwCastFunc>::OriginalType& rhs) const
        {
                return m_value == rhs;
        }

        /***************************************************************************************************************************/
        template<class oriType, template<class,class> class gwCastFunc>
        bool
        gwConvertShell<oriType,gwCastFunc>::operator !=(const gwConvertShell<oriType,gwCastFunc>& rhs) const
        {
                return m_value != rhs.m_value;
        }

        /***************************************************************************************************************************/
        template<class oriType, template<class,class> class gwCastFunc>
        bool
        gwConvertShell<oriType,gwCastFunc>::operator !=(const typename gwConvertShell<oriType,gwCastFunc>::OriginalType& rhs) const
        {
                return m_value != rhs;
        }

        /***************************************************************************************************************************/
        template<class oriType, template<class,class> class gwCastFunc>
        bool
        gwConvertShell<oriType,gwCastFunc>::operator <(const gwConvertShell<oriType,gwCastFunc>& rhs) const
        {
                return m_value < rhs.m_value;
        }

        /***************************************************************************************************************************/
        template<class oriType, template<class,class> class gwCastFunc>
        bool
        gwConvertShell<oriType,gwCastFunc>::operator <(const typename gwConvertShell<oriType,gwCastFunc>::OriginalType& rhs) const
        {
                return m_value < rhs;
        }

        /***************************************************************************************************************************/
        template<class oriType, template<class,class> class gwCastFunc>
        bool
        gwConvertShell<oriType,gwCastFunc>::operator >(const gwConvertShell<oriType,gwCastFunc>& rhs) const
        {
                return m_value > rhs.m_value;
        }

        /***************************************************************************************************************************/
        template<class oriType, template<class,class> class gwCastFunc>
        bool
        gwConvertShell<oriType,gwCastFunc>::operator >(const typename gwConvertShell<oriType,gwCastFunc>::OriginalType& rhs) const
        {
                return m_value > rhs;
        }

        /***************************************************************************************************************************/
        template<class oriType, template<class,class> class gwCastFunc>
        bool
        gwConvertShell<oriType,gwCastFunc>::operator <=(const gwConvertShell<oriType,gwCastFunc>& rhs) const
        {
                return m_value <= rhs.m_value;
        }

        /***************************************************************************************************************************/
        template<class oriType, template<class,class> class gwCastFunc>
        bool
        gwConvertShell<oriType,gwCastFunc>::operator <=(const typename gwConvertShell<oriType,gwCastFunc>::OriginalType& rhs) const
        {
                return m_value <= rhs;
        }

        /***************************************************************************************************************************/
        template<class oriType, template<class,class> class gwCastFunc>
        bool
        gwConvertShell<oriType,gwCastFunc>::operator >=(const gwConvertShell<oriType,gwCastFunc>& rhs) const
        {
                return m_value >= rhs.m_value;
        }

        /***************************************************************************************************************************/
        template<class oriType, template<class,class> class gwCastFunc>
        bool
        gwConvertShell<oriType,gwCastFunc>::operator >=(const typename gwConvertShell<oriType,gwCastFunc>::OriginalType& rhs) const
        {
                return m_value >= rhs;
        }

        /***************************************************************************************************************************/
        template<class oriType, template<class,class> class gwCastFunc>
        bool
        gwConvertShell<oriType,gwCastFunc>::AsBoolen() const
        {
                return gwCastFunc<bool, oriType>::gwCast(m_value);
        }

        /***************************************************************************************************************************/
        template<class oriType, template<class,class> class gwCastFunc>
        char
        gwConvertShell<oriType,gwCastFunc>::AsChar() const
        {
                return gwCastFunc<char, oriType>::gwCast(m_value);
        }

        /***************************************************************************************************************************/
        template<class oriType, template<class,class> class gwCastFunc>
        short
        gwConvertShell<oriType,gwCastFunc>::AsShort() const
        {
                return gwCastFunc<short, oriType>::gwCast(m_value);
        }

        /***************************************************************************************************************************/
        template<class oriType, template<class,class> class gwCastFunc>
        int
        gwConvertShell<oriType,gwCastFunc>::AsInt() const
        {
                return gwCastFunc<int, oriType>::gwCast(m_value);
        }

        /***************************************************************************************************************************/
        template<class oriType, template<class,class> class gwCastFunc>
        long
        gwConvertShell<oriType,gwCastFunc>::AsLong() const
        {
                return gwCastFunc<long, oriType>::gwCast(m_value);
        }

        /***************************************************************************************************************************/
        template<class oriType, template<class,class> class gwCastFunc>
        float
        gwConvertShell<oriType,gwCastFunc>::AsFloat() const
        {
                return gwCastFunc<float, oriType>::gwCast(m_value);
        }

        /***************************************************************************************************************************/
        template<class oriType, template<class,class> class gwCastFunc>
        double
        gwConvertShell<oriType,gwCastFunc>::AsDouble() const
        {
                return gwCastFunc<double, oriType>::gwCast(m_value);
        }

        /***************************************************************************************************************************/
        template<class oriType, template<class,class> class gwCastFunc>
        std::string
        gwConvertShell<oriType,gwCastFunc>::AsString() const
        {
                return gwCastFunc<std::string, oriType>::gwCast(m_value);
        }
}

#endif
